package hikari.gui.animationeditor;

import com.gooddies.wiring.annotations.WiringComponent;
import org.swig.jirr.IAnimatedMeshSceneNode;
import org.swig.jirr.ISceneNode;
import org.swig.jirr.IrrlichtDevice;
import org.swig.jirr.vector3df;

/**
 * @author sad
 */
@WiringComponent(singleton = true, lazy = true)
public class AnimationDiffRecounter {

    private AnimationDiffRecounter() {
        
    }

    public interface OnProcessFrame {

        void frameProcessed(int frame, int totalFrames);
    }

    public double[] recount(IAnimatedMeshSceneNode node, int etalonFrame, IrrlichtDevice device, OnProcessFrame event) {
        int currentFrame = (int) node.getFrameNr();
        int frameCount = (int) node.getMesh().getFrameCount();

        double[] etalonAngles = new double[(int) node.getJointCount()];
        node.setCurrentFrame(etalonFrame);
        device.run();
        device.getSceneManager().drawAll();
        node.animateJoints(true);
        calculateEtalonAngles(node, etalonAngles);

        double[] sigm = new double[frameCount];
        for (int i = 0; i < frameCount; i++) {
            sigm[i] = calculateFrameSigm(i, node, etalonAngles, device);
            event.frameProcessed(i, frameCount);
        }

        node.setCurrentFrame(currentFrame);
        return sigm;
    }

    private void calculateEtalonAngles(IAnimatedMeshSceneNode node, double[] etalonAngles) {
        int jointCount = (int) node.getJointCount();
        for (int i = 0; i < jointCount; i++) {
            ISceneNode bone = node.getJointNode(i);
            vector3df rotation = bone.getRotation();
            double val = Math.abs(rotation.getX()) + Math.abs(rotation.getY()) + Math.abs(rotation.getZ());
            etalonAngles[i] = val;
        }
    }

    private double calculateFrameSigm(int frame, IAnimatedMeshSceneNode node, double[] etalonAngles, IrrlichtDevice device) {
        node.setCurrentFrame(frame);
        device.run();
        device.getSceneManager().drawAll();
        node.animateJoints(true);
        int jointCount = (int) node.getJointCount();

        double sumsquare = 0;
        for (int i = 0; i < jointCount; i++) {
            ISceneNode bone = node.getJointNode(i);
            vector3df rotation = bone.getRotation();
            double val = Math.abs(rotation.getX()) + Math.abs(rotation.getY()) + Math.abs(rotation.getZ());
            sumsquare += (val - etalonAngles[i]) * (val - etalonAngles[i]);
        }
        double sigm = Math.sqrt(sumsquare / (double) jointCount);
        return sigm;
    }
}
